/*
 * 代号：凤凰
 * http://www.jphenix.org
 * 2019年4月27日
 * V4.0
 */
package com.jphenix.one.maven;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.jphenix.driver.nodehandler.FNodeHandler;
import com.jphenix.share.tools.HttpCall;
import com.jphenix.share.util.BaseUtil;
import com.jphenix.share.util.SFilesUtil;
import com.jphenix.standard.docs.ClassInfo;
import com.jphenix.standard.viewhandler.IViewHandler;

/**
 * 包下载器
 * 
 * 通过模拟页面访问方式到https://mvnrepository.com下载指定版本的包和依赖包
 * 
 * 2019-04-29 修改了解析错误，导致下载大量的无用文件
 * 2019-07-18 完善了代码
 * 
 * @author MBG
 * 2019年4月27日
 */
@ClassInfo({"2019-07-18 14:29","包下载器"})
public class PackageDownloader {

	private List<String> alreadyDownloadList = new ArrayList<String>(); //已经下载的信息序列
	private String objPath = null; //下载到目标绝对路径
	
	/**
	 * 构造函数
	 * @param objPath 下载到目标绝对路径
	 * @throws        异常
	 * @author MBG
	 */
	public PackageDownloader(String objPath) throws Exception {
		super();
		this.objPath = objPath;
		
		//构建目标文件夹
		SFilesUtil.createPath(objPath,null,true);
	}
	
	/**
	 * 执行下载
	 * @param groupId      包名（pom.xml中的groupId值）
	 * @param artifactId   集合中指定的模块名字
	 * @param ver          版本号
	 * @throws Exception   异常
	 * 2019年4月27日
	 * @author MBG
	 */
	public void download(String groupId,String artifactId,String ver,Map<String,String> headerMap) throws Exception {
		//验证是否已经下载过
		String key = groupId+"_"+artifactId+"_"+ver;
		if(alreadyDownloadList.contains(key)) {
			return;
		}
		alreadyDownloadList.add(key);
		
		System.out.println("准备分析：groupId:["+groupId+"] artifactId:["+artifactId+"] ver:["+ver+"]...");
		
		//获取页面
		String htmlContent = HttpCall.call(Go.BASE_URL+"/artifact/"+groupId+"/"+artifactId+"/"+ver);
		//构建页面对象
		IViewHandler mainVh = FNodeHandler.newBody(htmlContent).fcid("page");
		
		downloadFile(key,mainVh,headerMap);   //下载当前文件
		
		checkDependent(key,mainVh,headerMap); //检测依赖包
	}
	
	/**
	 * 下载当前页面包
	 * @param vh           页面内容
	 * @throws Exception   异常
	 * 2019年4月27日
	 * @author MBG
	 */
	private void downloadFile(String key,IViewHandler vh,Map<String,String> headerMap) throws Exception {
		//文件信息块
		IViewHandler area = vh.fnn("table");
		//超链接节点序列
		List<IViewHandler> aList = area.getChildNodesByAttribute("class","vbtn");
		IViewHandler downloadVh  = null; //待下载文件的节点
		String url = null; //下载地址
		for(IViewHandler ele:aList) {
			if(ele.nt().trim().startsWith("jar")) {
				downloadVh = ele;
				break;
			}
		}
		if(downloadVh==null) {
			System.out.println(key+" 没有获取到需要下载的文件...");
			return;
		}
		url = downloadVh.a("href");
		if(url==null || url.length()<1) {
			System.out.println(key+" 没有获取到需要下载的文件 代码段内容：\n"+downloadVh);
			return;
		}
		//文件名
		String fileName = SFilesUtil.getFileName(url);
		//判断文件是否存在
		File saveFile = new File(objPath+"/"+fileName);
		if(saveFile.exists()) {
			System.out.println(key+" 文件:["+fileName+"]已经存在，忽略下载...");
			return;
		}
		try {
			//下载文件
			System.out.println(key+" 准备下载文件：["+url+"]");
			HttpCall.downloadFile(url,null,null,objPath,headerMap);
			System.out.println(key+" 成功下载文件：["+fileName+"]");
		}catch(Exception e) {
			System.out.println(key+" 下载文件：["+fileName+"] 代码段内容：\n"+downloadVh+"\n出现错误："+e);
			e.printStackTrace();
		}
	}
	
	/**
	 * 检测关联包
	 * @param vh           页面内容
	 * @throws Exception   异常
	 * 2019年4月27日
	 * @author MBG
	 */
	private void checkDependent(String key,IViewHandler vh,Map<String,String> headerMap) throws Exception {
		//列表段序列
		List<IViewHandler> areaList = vh.getChildNodesByAttribute("class","version-section");
		IViewHandler dVh = null; //依赖信息列表节点
		for(IViewHandler ele:areaList) {
			if(ele.fnn("h2").nt().startsWith("Compile Dependencies")) {
				dVh = ele;
				break;
			}
		}
		if(dVh==null) {
			System.out.println(key+" 没有依赖包");
			return;
		}
		//行序列
		List<IViewHandler> trList = dVh.fnn("tbody").cnn("tr");
		List<IViewHandler> aList; //下载位置
		String url;    //下载页面地址
		String[] subs; //信息段
		for(IViewHandler tr:trList) {
			//获取依赖包锚点序列
			aList = tr.getChildNodesByAttribute("class","vbtn release");
			if(aList.size()<1) {
				continue;
			}
			url = aList.get(0).a("href");
			if(url.length()<1) {
				continue;
			}
			System.out.println(key+" 准备处理依赖包 url:["+url+"]");
			///artifact/org.neo4j/neo4j-kernel/3.5.5   开头有/ 也就是说，数组0是空字符串
			subs = BaseUtil.split(url,"/");
			if(subs.length<4) {
				continue;
			}
			//递归处理依赖包
			try {
				download(subs[2],subs[3],subs[4],headerMap);
			}catch(Exception e) {
				e.printStackTrace();
			}
		}
	}
}
